package REMC.monteCarlo;

import static java.lang.Integer.parseInt;

import java.io.IOException;
import java.util.Vector;
import java.util.concurrent.TimeUnit;

import main.Configuration;
import main.Grid;
import main.Sequence;
import REMC.objects.MyLogger;
import REMC.objects.Replica;
/**
 * @authors Tal & Adiel
 * 
 * this class is used to check the monte carlo algorithm.
 * the check is depended on the temperature that is set on the config.ini file
 * you can also run the test few times in a row by setting "numberOfRepeats".
 *
 */
public class MonteCarloMain {
	public static void main(String[] args) {
		
		//reading configuration file
		Configuration config = getConfiguration(args);
		Double tempature = config.tempature;
		Integer numberOfRepeats = config.numberOfRepeats;
		
		//setting up the logger
		MyLogger l = MyLogger.getLogger();
		l.Log("Starting monte carlo simualtion!");
		
		//creating monte carlo object
		MonteCarloSearch mcs = new MonteCarloSearch(config, true);
		
		//for Measuring the times of every search
		Vector<Long> Times = new Vector<Long>(numberOfRepeats);
		
		//starting execution or monte carlo, as many times as numberOfRepeats
		for (int i = 0;i < numberOfRepeats;i++){
			l.Log( "Starting monte carlo search Iteration: "+ i);
			l.Log("**************************************");
			Grid grid = new Grid(config.sequence.length(), config.dimensions);
			Sequence sequence = new Sequence( config.sequence);
			Replica replica = new Replica(config.dimensions, sequence, 
					config.random, grid, "testReplica",tempature);
			l.Log("Replica before search");
			l.Log(replica.toString());
			//configuring msc to the current iteration
			mcs.init(i);
			
			long startTime = System.currentTimeMillis();
			//running the algorithm!!
			replica = mcs.search(replica);		
			//writing monte carlo's results to file
			mcs.writeResultsToFile();
			long endTime = System.currentTimeMillis();
			long millis = endTime-startTime;
			String elapsed = String.format("%d min, %d sec", 
				    TimeUnit.MILLISECONDS.toMinutes(millis),
				    TimeUnit.MILLISECONDS.toSeconds(millis) - 
				    TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
				);
			
			l.Log("Replica after search");
			l.Log(replica.toString());
			l.Log( "Finished monte carlo search Iteration: "+ i);
			l.Log("Iteration "+ i+" took us : " + elapsed );
			Times.add(millis);//Adding current time to vector
			System.out.println("Iteration "+ i+" took: "+elapsed);
		}	
		l.Log("**************************************");
		l.close();
	}

	/**
	 * this method is copied from the GA.java class (in package main)
	 */
	private static Configuration getConfiguration(String[] argv) {
		if (argv.length != 2){
			throw new RuntimeException("Cannot run GA \n Usage: java main.GA <config file name> <seed>");
		}
		Configuration config;
		System.out.print("Loading Configuration ...\n");
		String configFileName = argv[0];
		MyLogger.getLogger().Log("Configuration file name "+configFileName);
		int seed;
		try {
			seed = parseInt(argv[1]);
		} catch (NumberFormatException ex)   { throw new RuntimeException("Cannot parse "+argv[1]+" as a seed.");   }

		try {
			config = new Configuration(configFileName, seed);
		}  catch (IOException ex1) {throw new RuntimeException("Failed to find, open or read configuration file: "+configFileName+"\n"+ex1);}

		MyLogger.getLogger().Log("OK!");
		return config;
	}

	
}
